/* $Header: clocktask.c,v 2.2 01/10/02 10:26:00 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME: clocktask.c                                            */
/* ============                                                        */
/*                                                                     */
/* Author: Rick Wikfors, Tom Przybylski                                */
/*                                                                     */
/* MODULE PURPOSE: Background NewtOS task for Clock Table execution.   */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include  <typedefs.h>
#include  <p_wkfile.h>
#include  <wkfile.h>
#include  <ramps.h>
#include  <zone_config.h>
#include  <config.h>
#include  <zone_status.h>
#include  <status.h>
#include  <error.h>
#include  <diag.h>
#include  <stddef.h>
#include  <i_op.h>
#include  <iomap.h>
#include  <std_ops.h>
#include  <task_pub.h>
#include  <exception.h>
#include  <timetable.h>
#include  <clock_ui.h>
#include  <valve_ui.h>
#include  <leds.h>
#include  <run_ui.h>
#include  <sequence.h>
#include  <seq_ui.h>
#include  <kbd_ui.h>


/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/

#pragma SECTION UDATA=pfail

TIME_TABLE Clock_Table;

#pragma SECTION UNDO

INT32      Last_Time;

/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/

/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/


const TableExecutor Clock_Table_Handlers[] = {
                   (TableExecutor) CT_NULL_EVENT,      /* Placeholer, indicates no event */
                   (TableExecutor) CTSetValve1State,
                   (TableExecutor) CTSetValve2State,
                   (TableExecutor) CTSetValve3State,
                   (TableExecutor) CTSetValve4State,
                   (TableExecutor) CTSetValve5State,
                   (TableExecutor) CTSetValve6State,
                   (TableExecutor) CTSetRelay1State,
                   (TableExecutor) CTSetRelay2State,
                   (TableExecutor) CTMultiValve,       /* Multiposition valve */
                   (TableExecutor) CTBlankRun,         /* Start Blank Run */
                   (TableExecutor) CTStartSeq,         /* Start Sequence  */
                   (TableExecutor) CTPrepRun,          /* Prep Run        */
                   (TableExecutor) CTColComp1,         /* Col Comp 1      */
                   (TableExecutor) CTColComp2,         /* Col Comp 2      */
                   (TableExecutor) CTColCompBoth,      /* Col Comp 12    */
                   (TableExecutor) CTLoadMethod,       /* Load Method     */
                   (TableExecutor) CTLoadSequence,     /* Load Sequence   */
                   (TableExecutor) CTDetOffsetSeek,    /* NPD, ECD offset */

                   };

RESOURCE Clock_Table_Exclusive_Lock;

/**begin_proto**/

void SetUpDefaultClockTable ( void )

/**end_proto**/
{

     U_INT8 i;

                       /* not avail, use whole table! */
     for ( i = 0 ; i < NUM_TIME_TABLE_ENTRIES ; i++ )
     {
          Clock_Table.Table[i].Type = (U_INT8) Available_Entry;
          Clock_Table.Table[i].Time = (INT32) 0xffffffff;
          Clock_Table.Table[i].Parm = (INT32) 0xffffffff;
     }

     Clock_Table.Current_Entry_Index = 0;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void ExecuteClockTable ( void )

/**end_proto**/
{

   U_INT8   index;
   TableExecutor handler;
   INT32    parm;

   /* NOTE: Table resource is unlocked in each branch of the /if/ to */
   /*       avoid a resource deadlock.  This allows the execution of */
   /*       the entry outside of the lock.  A "long" execution       */
   /*       handler, like the Gas Sampling Valve starting a run, will*/
   /*       not hang the keyboard then.  The index is advanced in    */
   /*       either /if/ branch so it can be done under the lock.     */


   if (IsrLockResource( &Clock_Table_Exclusive_Lock ) == TRUE )
   {
      index = Clock_Table.Current_Entry_Index;

      if ( (U_INT32) Clock_Table.Table[ index ].Time <= (U_INT32)GetClockTime())
      {
         handler = Clock_Table_Handlers[Clock_Table.Table[index].Type];
         parm    =  Clock_Table.Table[ index ].Parm;

         if ( index <= NUM_AVAIL_ENTRIES )
         {
            Clock_Table.Current_Entry_Index++;
         }

         ReleaseResource( &Clock_Table_Exclusive_Lock );

         if (RunInProgress() || SequenceInProgress() ||
             GetLSMSeqLock() || GetClockTableLock()  ||
             GetClockTableSeqLock() || GsvInjInProgress()  )
         {
            /* If we were to display/log skipping of entry */
            /* it would go here.  Decision made to skip    */
            /* events quietly.                             */
         }
         else
         {
            (*handler)( parm );   /* execute entry */
         }
      }
      else
      {
         ReleaseResource( &Clock_Table_Exclusive_Lock );
      }
   }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Initializes clock table pointer for current time of day.   */
/*    Is used by Startup, so has no resource lock.  If this module is  */
/*    to be used for things like loading clock tables, etc., it        */
/*    ***MUST***!!! be called with the resource lock in effect.        */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/

/**begin_proto**/

void ResetClockTablePointer ( void )

/**end_proto**/
{
    U_INT32  time;
    U_INT8   index;

    index = 0;
    time  = (U_INT32) GetClockTime();

    while ( (index <= NUM_AVAIL_ENTRIES) &&
            ((U_INT32) Clock_Table.Table[ index ].Time < time) )
    {
       index++;
    }

    Clock_Table.Current_Entry_Index = index;
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/

void ClockTableTask(void)
{
   INT32  time;
   INT32  parm;
   U_INT8 type;

   Last_Time = GetClockTime();

   while ( POWER_ON_TEST_IN_PROGRESS )    /* wait until power on tests finish */
   {
      Task_yield();
   }


   while (TRUE)                 /* Loop Forever */
   {
      Task_yield();             /* yield to other background tasks */

      UpdateTimeOfDay ();

      LockResource( &Clock_Table_Exclusive_Lock );

         time = GetClockTime();

         if (time < Last_Time)
         {
            Clock_Table.Current_Entry_Index = 0;
         }

         Last_Time = time;

      ReleaseResource( &Clock_Table_Exclusive_Lock );

      if ((GetClockTableEntry (1, &time, &type, &parm) != OK) ||
           GetLSMSeqLock() || GetClockTableLock()                )
      {
         TURN_CLOCK_TBL_LED_OFF()    /* No Clock Table */
      }
      else
      {
         TURN_CLOCK_TBL_LED_ON()     /* At least one entry */
      }

      ExecuteClockTable ();

      (void) parm;
      (void) type;
   }

}

